home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / ODMemMgr / Sources / MemMgr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-03  |  11.3 KB  |  475 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MemMgr.cpp
  3.  
  4.     Contains:    Procedural API for memory heaps
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1994-96 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.                  2/13/96    srf        Build variation for MacApp
  12.     
  13.          <8>    10/24/95    jpa        1293441: Added slush-fund.
  14.          <7>      8/4/95    DM        Leak detection [1267956]
  15.          <6>      6/7/95    jpa        Added MMConfiguration [1246897]
  16.          <5>      5/4/95    jpa        Added MMGetFreeSpace [1235657] and MMMove
  17.                                     [1246077]
  18.          <4>     12/5/94    jpa        Nuked errant pragma lib_export's. [1195676]
  19.          <3>    10/24/94    jpa        Constness [1194286]. MMSplice [1194287].
  20.          <2>     9/29/94    RA        1189812: Mods for 68K build.
  21.          <1>     9/14/94    jpa        first checked in
  22.  
  23.     To Do:
  24.     In Progress:
  25.         
  26. */
  27.  
  28.  
  29. #ifndef _MEMMGR_
  30. #include "MemMgr.h"
  31. #endif
  32.  
  33. #ifndef _MEMMGRPV_
  34. #include "MemMgrPv.h"
  35. #endif
  36.  
  37. #ifndef _MEMDEBG_
  38. #include "MemDebg.h"
  39. #endif
  40.  
  41.  
  42. #undef SURVEY_SIZES
  43.  
  44. #if defined(qMacApp)
  45. // Added the following prototype, it was missing from MemDebg.h. Future versions of that file should include it!!
  46. extern MMBoolean
  47. MMValidateMemoryRange( const void *start, const void *end );
  48. #endif
  49.  
  50.  
  51. //==============================================================================
  52. // GLOBAL VARIABLES
  53. //==============================================================================
  54.  
  55.  
  56. BestFitHeap    *gDefaultHeap;
  57.  
  58.  
  59. #ifdef SURVEY_SIZES
  60.     const int kNSizeBins = 100;
  61.     unsigned long gSizeBin[kNSizeBins];
  62.     unsigned long gNAllocations;
  63. #endif
  64.  
  65.  
  66. //========================================================================================
  67. // HEAP MANAGEMENT
  68. //========================================================================================
  69.  
  70.  
  71. long
  72. MMConfiguration( )
  73. {
  74.     return MM_DEBUG ?kMMDebugConfigMask :0;
  75. }
  76.  
  77.  
  78. //------------------------------------------------------------------------------
  79. // MMNewHeap
  80. //------------------------------------------------------------------------------
  81.  
  82. MemHeap* MMNewHeap( MMHeapLocation loc, size_t initialSize, size_t growAmount,
  83.                     const char *name )
  84. {
  85.     BestFitHeap *heap = new( (MMHeapLocation)loc )
  86.                                 BestFitHeap(initialSize,growAmount,0, (MMHeapLocation)loc);
  87.     if( heap ) {
  88.         heap->IBestFitHeap();
  89.         if( name )
  90.             heap->SetDescription(name);
  91. #if MM_DEBUG
  92.         if( gValidate>0 ) {
  93.             heap->SetZapOnAllocate(kMMTrue);
  94.             heap->SetZapOnFree(kMMTrue);
  95.             heap->SetAutoValidation(kMMTrue);
  96.         }
  97. #endif
  98.     }
  99.     return (MemHeap*) heap;
  100. }
  101.  
  102.  
  103. //------------------------------------------------------------------------------
  104. // MMDisposeHeap
  105. //------------------------------------------------------------------------------
  106.  
  107. void
  108. MMDisposeHeap( MemHeap *heap )
  109. {
  110.     delete (BestFitHeap*) heap;
  111. }
  112.  
  113.  
  114. //------------------------------------------------------------------------------
  115. // MMGetDefaultHeap
  116. //------------------------------------------------------------------------------
  117.  
  118. MemHeap*
  119. MMGetDefaultHeap( )
  120. {
  121.     return (MemHeap*) gDefaultHeap;
  122. }
  123.  
  124.  
  125. //------------------------------------------------------------------------------
  126. // MMSetDefaultHeap
  127. //------------------------------------------------------------------------------
  128.  
  129. MemHeap*
  130. MMSetDefaultHeap( MemHeap *heap )
  131. {
  132.     MM_ASSERT(heap!=kMMNULL);
  133.     MemHeap *oldDefault = (MemHeap*)gDefaultHeap;
  134.     gDefaultHeap = (BestFitHeap*)heap;
  135.     return oldDefault;
  136. }
  137.  
  138.  
  139. //========================================================================================
  140. // FREE SPACE MANAGEMENT
  141. //========================================================================================
  142.  
  143.  
  144. //----------------------------------------------------------------------------------------
  145. // MMGetFreeSpace
  146. //----------------------------------------------------------------------------------------
  147.  
  148. void
  149. MMGetFreeSpace( MemHeap *heapID, size_t *total, size_t *contig )
  150. {
  151.     BestFitHeap *heap = (BestFitHeap*)( heapID ?heapID :MMGetDefaultHeap() );
  152.     
  153.     size_t sysTotal, sysContig, heapTotal, heapContig;
  154.     
  155.     MMSystemFreeSpace(heap->GetLocation(),&sysTotal,&sysContig);
  156.     heapTotal = heap->BytesFree();
  157.     size_t incr = heap->GetSizeIncrement();
  158.     
  159.     if( sysContig < incr || sysTotal < incr+kPlatformMinFreeSpace ) {
  160.         // Not enough memory to grow heap, so we're limited to space in heap.
  161.         heapTotal = sysTotal;
  162.         heapContig = heap->LargestFreeBlock();
  163.     } else {
  164.         heapTotal += sysTotal;
  165.         heapContig = sysContig;
  166.     }
  167.     
  168.     if( total ) *total = heapTotal;
  169.     if( contig) *contig= heapContig;
  170. }
  171.  
  172.  
  173. MMBoolean
  174. MMAllocateSlushFund( MemHeap *heapID, size_t size, size_t allocSizeLimit )
  175. {
  176.     MemoryHeap *heap = heapID ?(MemoryHeap*)heapID :gDefaultHeap;
  177.     return heap->AllocateSlushFund(size,allocSizeLimit);
  178. }
  179.  
  180.  
  181. size_t
  182. MMSlushFundSize( MemHeap *heapID )
  183. {
  184.     MemoryHeap *heap = heapID ?(MemoryHeap*)heapID :gDefaultHeap;
  185.     return heap->GetSlushFundSize();
  186. }
  187.  
  188.  
  189. size_t
  190. MMFreeSlushFund( MemHeap *heapID )
  191. {
  192.     MemoryHeap *heap = heapID ?(MemoryHeap*)heapID :gDefaultHeap;
  193.     return heap->FreeSlushFund();
  194. }
  195.  
  196.  
  197.  
  198. //========================================================================================
  199. // OPERATIONS ON BLOCKS
  200. //========================================================================================
  201.  
  202.  
  203. #ifdef SURVEY_SIZES
  204. static void SurveySize( size_t size )
  205. {
  206.     size_t index = (size+3)>>2;
  207.     if( index >= kNSizeBins )
  208.         index = kNSizeBins-1;
  209.     gSizeBin[index]++;
  210.     gNAllocations++;
  211. }
  212. #endif
  213.  
  214.  
  215. //------------------------------------------------------------------------------
  216. // MMAllocate
  217. //------------------------------------------------------------------------------
  218.  
  219. void*
  220. MMAllocate( size_t size )
  221. {
  222. #if MM_DEBUG
  223.     if( (MMULong)size>BestFitBlock_kMaxBlockSize ) {
  224.         MM_WARN("Bogus size 0x%08lx for MMAllocate",size);
  225.         return kMMNULL;
  226.     }
  227.     
  228.     if( gHeapChecking>0 )
  229.         MMValidateHeap((MemHeap*)gDefaultHeap);
  230. #endif
  231.  
  232. #ifdef SURVEY_SIZES
  233.     SurveySize(size);
  234. #endif
  235.  
  236.     return gDefaultHeap->Allocate(size);
  237. }
  238.  
  239.  
  240. //------------------------------------------------------------------------------
  241. // MMAllocateIn
  242. //------------------------------------------------------------------------------
  243.  
  244. void*
  245. MMAllocateIn( size_t size, MemHeap *heap )
  246. {
  247. #if MM_DEBUG
  248.     if( (MMULong)size>BestFitBlock_kMaxBlockSize ) {
  249.         MM_WARN("Bogus size 0x%08lx for MMAllocate",size);
  250.         return kMMNULL;
  251.     }
  252.     
  253.     if( gHeapChecking>0 )
  254.         MMValidateHeap(heap);
  255. #endif
  256.  
  257. #ifdef SURVEY_SIZES
  258.     SurveySize(size);
  259. #endif
  260.  
  261.     return ((BestFitHeap*)heap)->Allocate(size);
  262. }
  263.  
  264.  
  265. //------------------------------------------------------------------------------
  266. // MMAllocateClear
  267. //------------------------------------------------------------------------------
  268.  
  269. void*
  270. MMAllocateClear( size_t size )
  271. {
  272.     return MMAllocateClearIn(size,(MemHeap*)gDefaultHeap);
  273. }
  274.  
  275.  
  276. //------------------------------------------------------------------------------
  277. // MMAllocateClearIn
  278. //------------------------------------------------------------------------------
  279.  
  280. void*
  281. MMAllocateClearIn( size_t size, MemHeap *heap )
  282. {
  283.     void *block = MMAllocateIn(size,heap);
  284.     if( block )
  285.         PlatformZapMem(block,size,0);
  286.     return block;
  287. }
  288.  
  289.  
  290. //------------------------------------------------------------------------------
  291. // MMReallocate
  292. //------------------------------------------------------------------------------
  293.  
  294. void*
  295. MMReallocate( void *block, size_t size )
  296. {
  297. #ifdef SURVEY_SIZES
  298.     SurveySize(size);
  299. #endif
  300.  
  301.     if( block==kMMNULL )
  302.         return gDefaultHeap->Allocate(size);
  303.     else {
  304.         BestFitHeap *heap = (BestFitHeap*)MMGetHeap(block);
  305.         if( heap )
  306.             return heap->Reallocate(block,size);
  307.         else
  308.             return kMMNULL;
  309.     }
  310. }
  311.  
  312.  
  313. //------------------------------------------------------------------------------
  314. // MMSplice
  315. //------------------------------------------------------------------------------
  316.  
  317. void*
  318. MMSplice( void *block, size_t offset, long delta )
  319. {
  320.     // If delta>0, insert bytes at offset. If delta<0, delete bytes at offset.
  321.     
  322.     if( delta==0 ) return block;
  323.     size_t oldSize = block ?MMBlockSize(block) :0;
  324.     MM_ASSERT(offset<=oldSize);
  325.     if( MM_DEBUG && delta<0 )
  326.         MM_ASSERT(offset-delta<=oldSize);
  327.         
  328.     size_t newSize = oldSize + delta;
  329.     void *newBlock;
  330.     if( newSize==0 )
  331.         newBlock = kMMNULL;
  332.     else {
  333.         BestFitHeap *heap = (BestFitHeap*)MMGetHeap(block);
  334.         if( heap )
  335.             newBlock = heap->Allocate(newSize);
  336.         else {
  337.             MM_WARN("Couldn't get block's heap in MMSplice");
  338.             return kMMNULL;
  339.         }
  340.         if( newBlock ) {
  341.             PlatformCopyMemory(block,newBlock,offset);
  342.             if( delta>0 )
  343.                 PlatformCopyMemory((char*)block+offset,(char*)newBlock+offset+delta, oldSize-offset);
  344.             else
  345.                 PlatformCopyMemory((char*)block+offset-delta,(char*)newBlock+offset, oldSize-offset+delta);
  346.         }
  347.     }
  348.     MMFree(block);
  349.     return newBlock;
  350. }
  351.  
  352.  
  353. //------------------------------------------------------------------------------
  354. // GetHeap [static]
  355. //------------------------------------------------------------------------------
  356.  
  357.  
  358. BestFitHeap*
  359. GetHeap( const void* block, const char *op )
  360. {
  361.     if (block == kMMNULL)
  362.     {
  363.         MM_WARN("%s(NULL) is bogus, dude",op);
  364.         return kMMNULL;
  365.     }
  366.     
  367. #if MM_DEBUG        
  368.     if( gValidate>0 )
  369.         if( !MMValidatePtr(block,gHeapChecking>0,op) )
  370.             return kMMNULL;
  371. #endif
  372.     
  373.     return (BestFitHeap*) gDefaultHeap->GetBlockHeap(block);    // Should be static but isn't
  374. }
  375.  
  376.  
  377.  
  378. //------------------------------------------------------------------------------
  379. // MMFree
  380. //------------------------------------------------------------------------------
  381.  
  382. void
  383. MMFree( void *block )
  384. {
  385.     if( block ) {
  386.         BestFitHeap *heap = GetHeap(block,"MMFree");
  387.         if( heap ) {
  388.             #if MM_DEBUG
  389.                 // The isObject flag should have been cleared by ODObject::SOMUninit!
  390.                 if( heap->BlockIsObject(block) )
  391.                     MM_WARN("Object %p unexpectedly disposed!",block);
  392.             #endif
  393.                     
  394.             heap->Free(block);
  395.         }
  396.     }
  397. }
  398.  
  399.  
  400. //------------------------------------------------------------------------------
  401. // MMBlockSize
  402. //------------------------------------------------------------------------------
  403.  
  404. size_t
  405. MMBlockSize( const void *block )
  406. {
  407.     BestFitHeap *heap = GetHeap(block,"MMBlockSize");
  408.     if( heap )
  409.         return heap->BlockSize(block);
  410.     else
  411.         return 0;
  412. }
  413.  
  414.  
  415. //------------------------------------------------------------------------------
  416. // MMGetHeap
  417. //------------------------------------------------------------------------------
  418.  
  419. MemHeap*
  420. MMGetHeap( const void* block )
  421. {
  422.     return (MemHeap*) GetHeap(block,"MMGetHeap");
  423. }
  424.  
  425.  
  426. //------------------------------------------------------------------------------
  427. // MMSetIsObject
  428. //------------------------------------------------------------------------------
  429.  
  430. void MMSetIsObject( void *block, char isObject )
  431. {
  432.     BestFitHeap *heap = GetHeap(block,"MMSetIsObject");
  433.     if( heap )
  434.         heap->SetBlockIsObject(block,isObject);
  435. }
  436.  
  437.  
  438. //------------------------------------------------------------------------------
  439. // MMIsObject
  440. //------------------------------------------------------------------------------
  441.  
  442. char MMIsObject( const void *block )
  443. {
  444.     BestFitHeap *heap = GetHeap(block,"MMIsObject");
  445.     if( heap )
  446.         return heap->BlockIsObject(block);
  447.     else
  448.         return kMMFalse;
  449. }
  450.  
  451.  
  452. //------------------------------------------------------------------------------
  453. // MMMove
  454. //------------------------------------------------------------------------------
  455.  
  456. void MMMove( void *dst, const void *src, size_t size )
  457. {
  458.     if( size!=0 && src!=dst ) {
  459. #if MM_DEBUG
  460.         static void *worldStart = LOWEST_POSSIBLE_ADDRESS();
  461.         static void *worldEnd   = HIGHEST_POSSIBLE_ADDRESS();
  462.         const void *srcEnd = (char*)src+size;
  463.         const void *dstEnd = (char*)dst+size;
  464.         if( srcEnd<worldStart || src>worldEnd || dstEnd<worldStart || dst>worldEnd
  465.                     || (size&~0x0FFFFFFF) )
  466.             MM_WARN("MMMove(%p,%p,%ld) looks weird", dst,src,size);
  467.         if( gValidate>0 ) {
  468.             MMValidateMemoryRange(src,srcEnd);
  469.             MMValidateMemoryRange(dst,(char*)dst+size);
  470.         }
  471. #endif
  472.         PlatformCopyMemory((void*)src,dst,size);
  473.     }
  474. }
  475.